package org.iabako.client.ui.form.user.customfield;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.LegendElement;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import org.iabako.client.navigation.NavigationController;
import org.iabako.client.tools.IabakoAsyncCallback;
import org.iabako.client.tools.Messages;
import org.iabako.client.ui.layout.field.CheckboxBoolean;
import org.iabako.client.ui.layout.field.InputText;
import org.iabako.client.ui.layout.field.LabelText;
import org.iabako.client.ui.layout.field.SelectList;
import org.iabako.client.ui.layout.widget.dialogbox.IabakoDialogBox;
import org.iabako.client.ui.layout.widget.tooltip.TooltipListener;
import org.iabako.shared.entity.business.CustomField;
import org.iabako.shared.entity.business.CustomFieldListItem;
import org.iabako.shared.entity.enumeration.CustomFieldType;
import org.iabako.shared.iservice.business.CustomFieldServiceAsync;
import org.iabako.shared.tools.GenericTools;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by jose on 19/09/14.
 */
public class CustomFieldForm extends Composite {

    interface MyUiBinder extends UiBinder<HTMLPanel, CustomFieldForm> {
    }

    protected final CustomFieldServiceAsync customFieldServiceAsync = CustomFieldServiceAsync.Util.getInstance();

    protected MyUiBinder binderForm = GWT.create(MyUiBinder.class);

    @UiField
    InputText title;
    @UiField
    SelectList type;
    @UiField
    LegendElement legend;
    @UiField
    DivElement deleteAction;
    @UiField
    HTMLPanel listPanel;
    @UiField
    SelectList listValues;
    @UiField
    InputText listNewValue;
    @UiField
    LabelText listNewValueAction;
    @UiField
    SelectList listDeleteValue;
    @UiField
    LabelText listDeleteValueAction;
    @UiField
    CheckboxBoolean criteriaSearch;
    @UiField
    DivElement arrowDown;
    @UiField
    DivElement arrowUp;

    ClientCustomFieldsConfigurationForm parent;
    CustomField customField;

    public CustomFieldForm(ClientCustomFieldsConfigurationForm clientCustomFieldsConfigurationForm, CustomField customField) {
        initWidget(binderForm.createAndBindUi(this));

        setHandlers();

        parent = clientCustomFieldsConfigurationForm;
        this.legend.setInnerText(Messages.getLabel("customfield_configuration_title", (parent.getCustomFields().size() + 1) + ""));

        this.customField = customField;

        this.criteriaSearch.setValue(customField.isCriteriaSearch());
        this.title.setValue(customField.getTitle());
        this.type.setEnumValue(customField.getCustomFieldType());

        if (this.type.getEnumValue() == CustomFieldType.list) {
            initListPanel();
        }
        if (this.customField.getId() != null) {
            //if customField exist in server DB, CustomFieldType edition is disabled.
            this.type.setEnabled(false);
        }
    }

    private void setHandlers() {

        DOM.sinkEvents(deleteAction.getParentElement(), Event.MOUSEEVENTS);
        DOM.setEventListener(deleteAction.getParentElement(), new TooltipListener(Messages.getLabel("custom_field_delete_title")));
        DOM.sinkEvents(deleteAction, Event.ONCLICK);
        DOM.setEventListener(deleteAction, new DeleteCustomFieldHandler(this));

        type.getSelectField().addChangeHandler(new ChangeHandler() {
            public void onChange(ChangeEvent event) {
                if (type.getEnumValue() == CustomFieldType.list) {
                    initListPanel();
                } else {
                    listPanel.setVisible(false);
                }
            }
        });

        listNewValueAction.getLabel().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                if (listValues.getValues().containsValue(listNewValue.getValue())
                        || GenericTools.isEmpty(listNewValue.getValue())) {
                    listNewValue.setValue(null);
                    return;
                }
                listValues.addValue(new Long(listValues.getValues().size()), listNewValue.getValue());
                setValuesToSelectLists(new ArrayList<String>(listValues.getValues().values()));

                List<String> items = parent.getCustomFieldListItemAdded().get(customField);
                if (items == null) {
                    items = new ArrayList<String>();
                    parent.getCustomFieldListItemAdded().put(customField, items);
                }
                items.add(listNewValue.getValue());

                listNewValue.setValue(null);
            }
        });

        listDeleteValueAction.getLabel().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {

                if (GenericTools.isEmpty(listDeleteValue.getValue())) {
                    return;
                }

                final String itemTextToDelete = (listDeleteValue.getSelectField().
                        getItemText(listDeleteValue.getSelectField().getSelectedIndex()));
                customFieldServiceAsync.getUsagesCustomFieldListValue(customField, itemTextToDelete, new IabakoAsyncCallback<Long>() {
                    public void onSuccess(Long usages) {
                        if (usages != null && usages > 0) {
                            IabakoDialogBox iabakoDialogBox = new IabakoDialogBox("custom_field_list_value_delete_title", Messages.getLabel("custom_field_list_value_delete_confirm_question", itemTextToDelete, usages + ""), true, "custom_field_list_value_delete_confirm") {
                                @Override
                                protected void customConfirmButtonHandler() {
                                    deleteCustomFieldListValue(itemTextToDelete);
                                }
                            };
                            iabakoDialogBox.setCloseOnlySimplePopup(true);
                            NavigationController.getInstance().show(iabakoDialogBox);
                        } else {
                            deleteCustomFieldListValue(itemTextToDelete);
                        }
                        super.onSuccess(usages);
                    }
                });
            }
        });

        DOM.sinkEvents(arrowUp.getParentElement(), Event.MOUSEEVENTS);
        DOM.setEventListener(arrowUp.getParentElement(), new TooltipListener(Messages.getLabel("custom_field_move_up")));
        DOM.sinkEvents(arrowUp, Event.ONCLICK);
        DOM.setEventListener(arrowUp, new EventListener() {
            public void onBrowserEvent(Event event) {
                parent.moveUp(customField);
            }
        });

        DOM.sinkEvents(arrowDown.getParentElement(), Event.MOUSEEVENTS);
        DOM.setEventListener(arrowDown.getParentElement(), new TooltipListener(Messages.getLabel("custom_field_move_down")));
        DOM.sinkEvents(arrowDown, Event.ONCLICK);
        DOM.setEventListener(arrowDown, new EventListener() {
            public void onBrowserEvent(Event event) {
                parent.moveDown(customField);
            }
        });
    }

    private void deleteCustomFieldListValue(String itemTextToDelete) {
        List<String> items = parent.getCustomFieldListItemDeleted().get(customField);
        if (items == null) {
            items = new ArrayList<String>();
            parent.getCustomFieldListItemDeleted().put(customField, items);
        }
        items.add(itemTextToDelete);
        listValues.removeValue((Long) listDeleteValue.getValue());
        setValuesToSelectLists(new ArrayList<String>(listValues.getValues().values()));
    }

    private void initListPanel() {
        listPanel.setVisible(true);

        if (customField.getId() != null && customField.getCustomFieldType() == CustomFieldType.list) {
            //customField exists in server DB
            customFieldServiceAsync.getCustomFieldsListItemValues(customField, new IabakoAsyncCallback<List<CustomFieldListItem>>() {
                public void onSuccess(List<CustomFieldListItem> result) {
                    List<String> itemText = new ArrayList<String>();
                    for (CustomFieldListItem item : result) {
                        itemText.add(item.getLabel());
                    }
                    setValuesToSelectLists(itemText);
                    super.onSuccess(result);
                }
            });
        }
    }

    private void setValuesToSelectLists(List<String> result) {
        int index = 0;
        Map<Long, String> resultFormat = new LinkedHashMap<Long, String>();
        for (String itemText : result) {
            resultFormat.put(new Long(index++), itemText);
        }
        listValues.setValues(resultFormat);
        listDeleteValue.setValues(resultFormat);
    }

    class DeleteCustomFieldHandler implements EventListener {
        CustomFieldForm customFieldForm;

        DeleteCustomFieldHandler(CustomFieldForm customFieldForm) {
            this.customFieldForm = customFieldForm;
        }

        public void onBrowserEvent(Event event) {
            customFieldServiceAsync.getUsagesCustomField(customFieldForm.getCustomField(), new IabakoAsyncCallback<Long>() {
                public void onSuccess(Long usages) {
                    if (usages != null && usages > 0) {
                        IabakoDialogBox iabakoDialogBox = new IabakoDialogBox("custom_field_delete_title", Messages.getLabel("custom_field_delete_confirm_question", usages + ""), true, "custom_field_delete_confirm") {
                            @Override
                            protected void customConfirmButtonHandler() {
                                parent.removeCustomFieldForm(customFieldForm);
                            }
                        };
                        iabakoDialogBox.setCloseOnlySimplePopup(true);
                        NavigationController.getInstance().show(iabakoDialogBox);
                    } else {
                        parent.removeCustomFieldForm(customFieldForm);
                    }
                    super.onSuccess(usages);
                }
            });
        }
    }

    public void setArrowUpVisible(boolean visible) {
        arrowUp.getStyle().setDisplay(visible ? Style.Display.BLOCK : Style.Display.NONE);
    }

    public void setArrowDownVisible(boolean visible) {
        arrowDown.getStyle().setDisplay(visible ? Style.Display.BLOCK : Style.Display.NONE);
    }

    public CustomField getCustomField() {
        return customField;
    }
}
